<?php

// 解析固定宽度字段数据记录

// 问题
// 需要将固定宽度记录分解为字符串

// 解决方案 用 substr or unpack()

// 用 substr 的知道每一行为每个字段分配的固定数目的字符

$bookList = <<<END
Elmer Gantry              Sinclair lewis  1927
The Scarlatti Inheritance Robert Ludlum   1971
Sophie's Mosaic           William Styron  1979
END;

// 每一行上，书名占前25个字符，作者姓名占接下来15个字符，出版年代占后面的4个字符。
// 知道了这些字段宽度，就能很容易地使用 substr() 将这些字段解析为一个数组

$books = explode("\n", $bookList);

$len = count($books);
for ($i = 0; $i < $len; $i++) {
    $bookArr[$i]['title'] = substr($books[$i], 0, 25);
    $bookArr[$i]['author'] = substr($books[$i], 25, 15);
    $bookArr[$i]['publication_year'] = substr($books[$i], 40, 4);
}

// 还可以是

function fixed_width_substr($fields, $data)
{
    $line = [];
    $len = count($data);
    for ($i = 0; $i < $len; $i++) {
        $linePos = 0;
        foreach ($fields as $fieldName => $fieldLength) {
            $line[$i][$fieldName] = rtrim(substr($data[$i], $linePos, $fieldLength));
            $linePos += $fieldLength;
        }
    }
    return $line;
}

$fields = ['title' => 25, 'author' => 15, 'publication_year' => 4];

//$book_array = fixed_width_substr($fields, $books);

// unpack

function fixed_width_unpack($format_string, $data)
{
    $line = [];
    $len = count($data);
    for ($i = 0; $i < $len; $i++) {
        $line[$i] = unpack($format_string, $data[$i]);
    }
    return $line;
}

$book_array = fixed_width_unpack('A25title/A15author/A4publication_year',$books);


/**************************************************************
 *  如果固定宽度字段是字符串，substr()和 unpack()的功能是相同的，不过如果
 *  字段元素不只是字符串，unpack() 则更好
 ***************************************************************/

/**************************************************************
 *  如果所有字段的大小都相同，可以使用 str_split()，这是分解输入数据的一个
 *  便捷方法，它会返回一个数组
 ***************************************************************/

$line_of_data = 'Elmer Gantry              Sinclair lewis  1927';
$fileds = str_split($line_of_data,32);
var_dump($fileds);
/*
array(2) {
  [0]=>
  string(32) "Elmer Gantry              Sincla"
  [1]=>
  string(14) "ir lewis  1927"
}
*/

